package demo.algorithm.stream;

import com.alibaba.fastjson.JSON;
import com.tdunning.math.stats.AVLTreeDigest;
import com.tdunning.math.stats.MergingDigest;
import com.tdunning.math.stats.TDigest;
import org.junit.Test;

import java.util.Arrays;
import java.util.Random;

/**
 *
 */
public class TDigestDemo {

    public static void print(TDigest tDigest) {

    }

    @Test
    public void testAVLTreeDigest() {
        double compression = 100;

        AVLTreeDigest tDigest = new AVLTreeDigest(compression);

        Random random = new Random();
        int dataSize = 1000000;
        for (int i = 0; i < dataSize; i++) {
            double d = random.nextDouble();
            tDigest.add(d);
        }
        System.out.println(tDigest + " = " + JSON.toJSONString(tDigest, true));
        double max = tDigest.getMax();
        double min = tDigest.getMin();
        long size = tDigest.size();
        long byteSize = tDigest.byteSize();
        System.out.println("size = " + size + "，Max = " + max + "，Min = " + min + "，byteSize = " + byteSize);

        System.out.println("百分位计算：");
        double quantile = 0.5;
        System.out.println(String.format("Quantile(%s) = %s ", quantile, tDigest.quantile(quantile)));
        quantile = 0.95;
        System.out.println(String.format("Quantile(%s) = %s ", quantile, tDigest.quantile(quantile)));
        quantile = 0.99;
        System.out.println(String.format("Quantile(%s) = %s ", quantile, tDigest.quantile(quantile)));
        quantile = 0.9999;
        System.out.println(String.format("Quantile(%s) = %s ", quantile, tDigest.quantile(quantile)));

    }

    @Test
    public void testMergingDigest() {
        double compression = 100;

        MergingDigest tDigest = new MergingDigest(compression);

        Random random = new Random();
        int dataSize = 1000000;
        for (int i = 0; i < dataSize; i++) {
            double d = random.nextDouble();
            tDigest.add(d);
        }
        System.out.println(tDigest);
        double max = tDigest.getMax();
        double min = tDigest.getMin();
        long size = tDigest.size();
        long byteSize = tDigest.byteSize();
        System.out.println("size = " + size + "，Max = " + max + "，Min = " + min + "，byteSize = " + byteSize);

        System.out.println("百分位计算：");
        double quantile = 0.5;
        System.out.println(String.format("Quantile(%s) = %s ", quantile, tDigest.quantile(quantile)));
        quantile = 0.95;
        System.out.println(String.format("Quantile(%s) = %s ", quantile, tDigest.quantile(quantile)));
        quantile = 0.99;
        System.out.println(String.format("Quantile(%s) = %s ", quantile, tDigest.quantile(quantile)));
        quantile = 0.9999;
        System.out.println(String.format("Quantile(%s) = %s ", quantile, tDigest.quantile(quantile)));

    }

    @Test
    public void testTDigest2() {
        Random random = new Random();
        for (double compression : new double[]{10, 20, 50, 100, 200, 500, 1000, 2000}) {
            TDigest dist = new MergingDigest(compression);
            double[] data = new double[100000];
            for (int i = 0; i < 100000; i++) {
                double x = random.nextDouble();
                dist.add(x);
                data[i] = x;
            }
            dist.compress();
            Arrays.sort(data);

            for (double q : new double[]{0.00001, 0.0001, 0.001, 0.01, 0.1, 0.5, 0.9, 0.99, 0.999, 0.9999, 0.99999}) {
                double x1 = dist.quantile(q);
            }
        }
    }


}
